package cc.tuhaolicai.mt.user.mobile.tool;

import org.asyou.redis.dao.IRedisAdapter;
import org.asyou.redis.dao.RedisAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.tools.constant.StrConst;
import pro.tools.data.ToolSerialize;
import redis.clients.jedis.Jedis;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Created by tuhao on 2017/6/28.
 */
public class ToolRedis {

    private static final Logger log = LoggerFactory.getLogger(ToolRedis.class);
    private static final String OK = "OK";

    public static byte[] findBytes(byte[] bytes) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.get(bytes);
        }
    }

    public static String findString(String key) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.get(key);
        }
    }

    public static Map<String, String> findMap(String key) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.hgetAll(key);
        }
    }

    public static List<String> findList(String key) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.lrange(key, 0, -1);
        }
    }

    public static <T> T findAny(String key) {
        try (Jedis jedis = Factory.getJedis()) {
            byte[] bytes = jedis.get(key.getBytes(StrConst.DEFAULT_CHARSET_NAME));
            return bytes == null ? null : ToolSerialize.unserialize(bytes);
        } catch (Exception e) {
            log.error("Redis反序列号化失败！,key：" + key, e);
        }
        return null;
    }

    public static Boolean setString(String key, String val) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.set(key, val).equalsIgnoreCase(OK);
        }
    }

    public static Boolean setString(String key, String val, int expireTime) {
        try (Jedis jedis = Factory.getJedis()) {
            boolean ignoreCase = jedis.set(key, val).equalsIgnoreCase(OK);
            jedis.expire(key, expireTime); //单位是秒
            return ignoreCase;
        }
    }

    public static String getString(String key) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.get(key);
        }
    }

    public static Boolean setByte(byte[] key, byte[] val) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.set(key, val).equalsIgnoreCase(OK);
        }
    }

    public static Boolean setList(String key, String... value) {
        try (Jedis jedis = Factory.getJedis()) {
            jedis.del(key);
            for (String one : value) {
                jedis.lpush(key, one);
            }
            return true;
        }
    }

    public static Boolean setList(String key, List<String> value) {
        try (Jedis jedis = Factory.getJedis()) {
            jedis.del(key);
            value.forEach(one -> jedis.lpush(key, one));
            return true;
        }
    }

    public static Boolean setMap(String key, Map<String, String> value) {
        try (Jedis jedis = Factory.getJedis()) {
            return jedis.hmset(key, value).equalsIgnoreCase(OK);
        }
    }

    public static <T> Boolean setAny(String key, T t) {
        try (Jedis jedis = Factory.getJedis()) {
            jedis.del(key);
            return jedis.set(key.getBytes(StrConst.DEFAULT_CHARSET_NAME), ToolSerialize.serialize(t)).equalsIgnoreCase(OK);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static <T> Boolean setAny(String key, T t, int expireTime) {
        try (Jedis jedis = Factory.getJedis()) {
            if (t == null) {
                return false;
            }
            //String set = jedis.set(key.getBytes(StrConst.DEFAULT_CHARSET_NAME)
            //        , ToolSerialize.serialize(t)
            //        , "XX".getBytes(StrConst.DEFAULT_CHARSET_NAME)/*NX -- Only set the key if it does not already exist. XX -- Only set the key if it already exist*/
            //        , "EX".getBytes(StrConst.DEFAULT_CHARSET_NAME)/*秒*/
            //        , expireTime);
            String set = jedis.setex(key.getBytes(StrConst.DEFAULT_CHARSET_NAME), expireTime, ToolSerialize.serialize(t));
            return set.equalsIgnoreCase(OK);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static Boolean del(String string) {
        try (Jedis jedis = Factory.getJedis()) {
            Long del = jedis.del(string);
            return del == 1L;
        }
    }

    public static class Factory {
        public static Jedis getJedis() {
            Jedis jedis = null;
            try {
                jedis = getAdapter().getHost().getRedis();
                return jedis;
            } catch (Exception e) {
                if (jedis != null) {
                    jedis.close();
                }
                String message = "初始化Jedis失败！";
                log.warn(message);
                throw new RuntimeException(message, e);
            }
        }


        private static volatile String defaultAdapterId;

        private static IRedisAdapter instance;

        public static void setDefaultAdapterId(String defaultAdapterId) {
            Factory.defaultAdapterId = defaultAdapterId;
        }

        public static String getDefaultAdapterId() {
            return defaultAdapterId;
        }

        public static IRedisAdapter getAdapter() {
            if (instance == null) {
                try {
                    instance = new RedisAdapter(defaultAdapterId);
                } catch (Exception e) {
                    String message = "初始化RedisAdapter失败！";
                    log.warn(message, e);
                    throw new RuntimeException(message, e);
                }
            }
            return instance;
        }
    }
}